package com.justgame.project.service.just.service;

import com.justgame.project.cloud.common.entity.PageRequest;
import com.justgame.project.cloud.common.enums.FileTypeEnum;
import com.justgame.project.cloud.common.exception.Exc;
import com.justgame.project.cloud.common.util.FileUtils;
import com.justgame.project.cloud.common.util.IdUtils;
import com.justgame.project.cloud.common.util.ObjUtil;
import com.justgame.project.cloud.common.util.ShiroUtils;
import com.justgame.project.service.api.dto.*;
import com.justgame.project.service.api.entity.JustGameType;
import com.justgame.project.service.api.feign.ISysFileInfoClient;
import com.justgame.project.service.api.vo.*;
import com.justgame.project.service.just.mapper.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
@Transactional
@Slf4j
public class JustGameInfoService {
    @Resource
    private JustGameInfoMapper justGameInfoMapper;

    @Resource
    private JustGameCloudMapper gameCloudMapper;

    @Resource
    private JustPlatformMapMapper platformMapMapper;

    @Resource
    private JustGamePlatformMapper platformMapper;

    @Resource
    private JustGameTypeMapMapper gameTypeMapMapper;

    @Resource
    private JustGameAdditionMapper gameAdditionMapper;

    @Resource
    private ISysFileInfoClient sysFileInfoClient;

    @Resource
    private JustGameTypeMapper gameTypeMapper;

    @Resource
    private JustGameScoreMapper scoreMapper;

    @Cacheable(cacheNames = {"Games"},key = "'GamePage'+#pageRequest")
    public PageRequest<JustGameInfoVO> selectPage(JustGameInfoDTO dto, PageRequest<JustGameInfoVO> pageRequest) {
        pageRequest.startPage();
        List<JustGameInfoVO> voList = justGameInfoMapper.Select(dto);
        voList.forEach(this::buildDetail);
        return pageRequest.BuildPageInfo(voList);
    }

    public PageRequest<?> searchGame(JustGameInfoDTO dto, PageRequest pageRequest) {
        pageRequest.startPage();
        List<Map<String, Object>> voList = justGameInfoMapper.getSearchGames(dto);
        if (voList.size() > 0){
            voList.forEach( map -> {
               String[] platforms = ((String)map.get("platforms")).split(",");
               map.put("platforms",platforms);
            });
        }
        return pageRequest.BuildPageInfo(voList);
    }

    public PageRequest<?> getSimpleList(JustGameInfoDTO dto, PageRequest pageRequest) {
        pageRequest.startPage();
        List<Map<String, Object>> voList = justGameInfoMapper.getSimpleList(dto);
        return pageRequest.BuildPageInfo(voList);
    }

    @Cacheable(cacheNames = {"Games"},key = "'GameDetail'+#id")
    public JustGameInfoVO getSecretDetail(String id) {
        if (StringUtils.isBlank(id)) {
            throw new Exc("抱歉咯！请先选择要查看的数据后再试吧~");
        }

        /* 构建查询JustGameInfo实体类 */
        JustGameInfoDTO gameInfoDTO = new JustGameInfoDTO();
        gameInfoDTO.setId(id);
        List<JustGameInfoVO> results = justGameInfoMapper.Select(gameInfoDTO);
        if (results == null || results.size() == 0) {
            throw new Exc("抱歉咯！您选择要查看的数据不存在哦~");
        }

        JustGameInfoVO result = results.get(0);
        buildDetail(result);
        return result;
    }

    @Cacheable(cacheNames = {"Games"},key = "'GameDetailMap'+#id")
    public Map<String, Object> getDetail(String id) {
        if (StringUtils.isBlank(id)) {
            throw new Exc("抱歉咯！请先选择要查看的数据后再试吧~");
        }
        /* 获取用户Id，如果有的话 */
        String userId = null;
        try {
            userId = ShiroUtils.getUserId();
        } catch (Exception ignored) {
        }
        /* 查询游戏相关讯息 */
        Map<String, Object> maps = justGameInfoMapper.SelectDetail(id, userId);
        if (maps == null || maps.size() == 0) {
            throw new Exc("抱歉咯！您选择要查看的数据不存在哦~");
        }
        /* 构建返回体 */
        Map<String, Object> results = new HashMap<>();
        /* 查询评分 */
        results.put("scoreDetail", scoreMapper.getScorePercent((String) maps.get("id")));
        /* 遍历查询的信息，填充返回体 */
        maps.forEach((k, v) -> {
            if (v instanceof String) {
                String val = (String) v;
                if ("platforms".equals(k) && StringUtils.isNotBlank(val)) {
                    /* 构建查询JustPlatformMap实体类 */
                    JustGamePlatformDTO platform = new JustGamePlatformDTO();
                    platform.setIds(Arrays.asList(val.split(",")));
                    List<JustGamePlatformVO> platforms = platformMapper.getList(platform);
                    results.put("platformList", platforms);
                    return;
                } else if ("types".equals(k) && StringUtils.isNotBlank(val)) {
                    /* 构建查询JustGameTypeMap实体类 */
                    JustGameTypeDTO typeMapDTO = new JustGameTypeDTO();
                    typeMapDTO.setIds(Arrays.asList(val.split(",")));
                    List<JustGameType> typeMaps = gameTypeMapper.getList(typeMapDTO);
                    results.put("typeList", typeMaps.stream().map(JustGameType::getChineseName).collect(Collectors.toList()));
                    return;
                } else if ("photos".equals(k) && StringUtils.isNotBlank(val)) {
                    results.put("photos", val.split(","));
                    return;
                }
            }
            results.put(k, v);
        });
        return results;
    }

    /**
     * 构建详情内容
     *
     * @param vo
     */
    private void buildDetail(JustGameInfoVO vo) {
        /* 构建查询JustGameAddition实体类 */
        JustGameAdditionDTO additionDTO = new JustGameAdditionDTO();
        additionDTO.setGameInfoId(vo.getId());
        List<JustGameAdditionVO> additions = gameAdditionMapper.getList(additionDTO);
        if (additions != null && additions.size() > 0) {
            vo.setGamePictures(additions.stream().filter(item -> item.getType() == 1).map(JustGameAdditionVO::getUrl).collect(Collectors.toList()));
            List<String> videos = additions.stream().filter(item -> item.getType() == 2).map(JustGameAdditionVO::getUrl).collect(Collectors.toList());
            if (videos.size() > 0) {
                vo.setVideoUrl(videos.get(0));
            }
        }

        /* 构建查询JustPlatformMap实体类 */
        JustPlatformMapDTO platformMapDTO = new JustPlatformMapDTO();
        platformMapDTO.setGameInfoId(vo.getId());
        List<JustPlatformMapVO> platformMaps = platformMapMapper.getList(platformMapDTO);
        if (platformMaps != null && platformMaps.size() > 0) {
            vo.setPlatforms(platformMaps.stream().map(JustPlatformMapVO::getGamePlatformId).collect(Collectors.toList()));
        }

        /* 构建查询JustGameTypeMap实体类 */
        JustGameTypeMapDTO typeMapDTO = new JustGameTypeMapDTO();
        typeMapDTO.setGameId(vo.getId());
        List<JustGameTypeMapVO> typeMaps = gameTypeMapMapper.getList(typeMapDTO);
        if (typeMaps != null && typeMaps.size() > 0) {
            vo.setTypes(typeMaps.stream().map(JustGameTypeMapVO::getTypeId).collect(Collectors.toList()));
        }
    }

    @CacheEvict(cacheNames = {"Games"})
    public boolean userUpdateGame(JustGameInfoDTO dto) {
        if (StringUtils.isBlank(dto.getId())) {
            throw new Exc("id不可为空");
        }
        if (!ObjUtil.isMine(justGameInfoMapper.SelectById(dto.getId()))) {
            throw new Exc("您无法修改不是你创建的数据哦！");
        }
        return updateGame(dto);
    }

    /**
     * 删除
     */
    @CacheEvict(cacheNames = {"Games"})
    public boolean adminDeleteGames(JustGameInfoDTO dto) {
        if ((dto.getIds() == null || dto.getIds().size() == 0) && StringUtils.isBlank(dto.getId())) {
            throw new Exc("请选择至少一条要删除的数据！");
        }

        if (StringUtils.isNotBlank(dto.getId())) {
            deleteOne(dto);
        } else {
            dto.getIds().forEach(id -> {
                JustGameInfoDTO newDto = new JustGameInfoDTO();
                newDto.setId(id);
                deleteOne(newDto);
            });
        }
        return justGameInfoMapper.Delete(dto) > 0;
    }

    @CacheEvict(cacheNames = {"Games"})
    public void deleteOne(JustGameInfoDTO dto) {
        /* 删除封面图文件 */
        JustGameInfoVO gameInfo = justGameInfoMapper.SelectById(dto.getId());
        if (StringUtils.isNotBlank(gameInfo.getImages())) {
            SysFileInfoDTO file = new SysFileInfoDTO();
            file.setPath(gameInfo.getImages());
            sysFileInfoClient.deleteFile(file);
        }

        /* 删除相关数据 */
        JustGameInfoDTO dto1 = new JustGameInfoDTO();
        dto1.setId(dto.getId());
        dto1.setIsUseOldResource(false);
        saveOrUpdateOtherData(dto1);
    }

    /**
     * 更新
     */
    @CacheEvict(cacheNames = {"Games"})
    public boolean updateGame(JustGameInfoDTO dto) {
        if (StringUtils.isBlank(dto.getId())) {
            throw new Exc("id不可为空");
        }
        if (dto.getIsUseOldResource() == null) {
            throw new Exc("请选择是否复用之前网盘资源信息！");
        }

        /* 查询源数据 */
        JustGameInfoVO oldData = justGameInfoMapper.SelectById(dto.getId());
        if (oldData == null) {
            throw new Exc("修改的源数据数据不存在！");
        }

        /* 删除源数据中的头像文件 */
        if (StringUtils.isBlank(dto.getImages()) &&
                StringUtils.isNotBlank(oldData.getImages())) {
            SysFileInfoDTO file = new SysFileInfoDTO();
            file.setPath(oldData.getImages());
            sysFileInfoClient.deleteFile(file);
        }

        ObjUtil.inject(dto, false);
        boolean temp = justGameInfoMapper.UpdateById(dto) > 0;
        if (!temp) {
            return false;
        }

        saveOrUpdateOtherData(dto);
        return true;
    }

    @CacheEvict(cacheNames = {"Games"})
    public void saveOrUpdateOtherData(JustGameInfoDTO dto) {
        /* 判断是否不再复用旧资源 */
        if (dto.getIsUseOldResource() != null && !dto.getIsUseOldResource()) {
            /* 构建网盘资源条件对象 */
            JustGameCloudDTO cloudDTO = new JustGameCloudDTO();
            cloudDTO.setGameInfoId(dto.getId());
            gameCloudMapper.Delete(cloudDTO);
        }

        if (dto.getClouds() != null && dto.getClouds().size() > 0) {
            /* 保存网盘资源 */
            dto.getClouds().forEach(cloud -> {
                cloud.setId(IdUtils.create());
                cloud.setGameInfoId(dto.getId());
                ObjUtil.inject(cloud, true);
                gameCloudMapper.Insert(cloud);
            });
        }

        /* 构建游戏平台条件对象 */
        JustPlatformMapDTO platformMapDTO = new JustPlatformMapDTO();
        platformMapDTO.setGameInfoId(dto.getId());
        platformMapMapper.Delete(platformMapDTO);

        if (dto.getPlatforms() != null && dto.getPlatforms().size() > 0) {
            /* 游戏平台一对多关系 */
            dto.getPlatforms().forEach(platformId -> {
                JustPlatformMapDTO platformMap = new JustPlatformMapDTO();
                platformMap.setId(IdUtils.create());
                platformMap.setGameInfoId(dto.getId());
                platformMap.setGamePlatformId(platformId);
                platformMapMapper.Insert(platformMap);
            });
        }

        /* 构建游戏类型条件对象 */
        JustGameTypeMapDTO typeMapDTO = new JustGameTypeMapDTO();
        typeMapDTO.setGameId(dto.getId());
        gameTypeMapMapper.Delete(typeMapDTO);

        if (dto.getTypes() != null && dto.getTypes().size() > 0) {

            /* 游戏类型一对多关系 */
            dto.getTypes().forEach(typeId -> {
                JustGameTypeMapDTO typeMap = new JustGameTypeMapDTO();
                typeMap.setId(IdUtils.create());
                typeMap.setTypeId(typeId);
                typeMap.setGameId(dto.getId());
                gameTypeMapMapper.Insert(typeMap);
            });
        }

        /* 查询出所有曾经的资源地址，为接下来比对废弃资源做准备 */
        List<String> oldUrls = gameAdditionMapper.getGameUrls(dto.getId());
        if (dto.getAdditions() != null && dto.getAdditions().size() > 0) {
            /* 新的资源地址 */
            List<String> newUrls = dto.getAdditions().stream().map(JustGameAdditionDTO::getUrl).collect(Collectors.toList());

            List<String> finalOldUrls = oldUrls;
            List<String> willInsert = newUrls.stream().filter((newUrl) -> !finalOldUrls.contains(newUrl)).collect(Collectors.toList());
            oldUrls = finalOldUrls.stream().filter((oldUrl) -> !newUrls.contains(oldUrl)).collect(Collectors.toList());

            /* 附加资源一对多关系 */
            willInsert.forEach(url -> {
                JustGameAdditionDTO additionDTO = new JustGameAdditionDTO();
                ObjUtil.inject(additionDTO, true);
                additionDTO.setUrl(url);
                additionDTO.setGameInfoId(dto.getId());
                String suffix = FileUtils.getFileUrlSuffix(url);
                if (StringUtils.isBlank(suffix)) {
                    throw new Exc("抱歉咯！未知的文件格式是无法保存的哦！");
                } else if (FileTypeEnum.Image.isContains(suffix)) {
                    additionDTO.setType(1);
                } else if (FileTypeEnum.Video.isContains(suffix)) {
                    additionDTO.setType(2);
                } else {
                    throw new Exc(String.format("抱歉咯！您上传的文件中含有{%s}文件，暂不支持保存该文件哦！", suffix));
                }
                gameAdditionMapper.Insert(additionDTO);
            });
        }
        if (oldUrls != null && oldUrls.size() != 0) {
            sysFileInfoClient.deleteFiles(oldUrls);
            /* 构建游戏附加资源条件对象 */
            JustGameAdditionDTO additionDTO = new JustGameAdditionDTO();
            additionDTO.setGameInfoId(dto.getId());
            additionDTO.setUrls(oldUrls);
            ObjUtil.inject(additionDTO, false);
            gameAdditionMapper.Delete(additionDTO);
        }
    }

    @CacheEvict(cacheNames = {"Games"})
    public boolean saveData(JustGameInfoDTO dto) {
        ObjUtil.inject(dto, true);
        justGameInfoMapper.Insert(dto);
        saveOrUpdateOtherData(dto);
        return true;
    }

    /**
     * 获取推荐游戏
     */
    @Cacheable(cacheNames = {"Games"},key = "'PopularGames'")
    public List<?> getPopularGames() {
        //return justGameInfoMapper.getPopularGames();
        PageRequest pageRequest = new PageRequest();
        pageRequest.setOrderBy("viewCount");
        pageRequest.setSize(30);
        pageRequest.setPage(1);
        return searchGame(new JustGameInfoDTO(),pageRequest).getRows();
    }

    /**
     * 加载最新上架
     */
    @Cacheable(cacheNames = {"Games"},key = "'NewReleasesGames'")
    public List<?> getNewReleasesGames() {
        PageRequest pageRequest = new PageRequest();
        pageRequest.setOrderBy("jgi.create_date");
        pageRequest.setSize(30);
        pageRequest.setPage(1);
        return searchGame(new JustGameInfoDTO(),pageRequest).getRows();
        //return justGameInfoMapper.getNewReleasesGames();
    }

    @Cacheable(cacheNames = {"Games"},key = "'GameDetail'+#id")
    public JustGameInfoVO selectGameInfoById (String id){
        return justGameInfoMapper.SelectById(id);
    }

    /**
     * 加载口碑最佳
     */
    @Cacheable(cacheNames = {"Games"},key = "'BestEvaluationGames'")
    public List<Map<String, Object>> getBestEvaluationGames() {
        return justGameInfoMapper.getBestEvaluationGames();
    }
}
